﻿using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using VisionCloud.Domain.Common;
using VisionCloud.Utility.Security;
using VisionCloud.Web;
using Xunit;
using Xunit.Abstractions;

namespace UnitTest.Tests.Controllers
{
    /// <summary>
    /// 单元测试基础类
    /// </summary>
    public class TestBase : IClassFixture<CustomWebApplicationFactory<Startup>>
    {
        protected readonly IServiceProvider serviceProvider;
        protected readonly ITestOutputHelper outPut;
        protected readonly HttpClient httpClient;
        private readonly string _userName = "18144775598";  // 登录用户名
        private readonly string _password = "abc@123456";   // 登录密码

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="factory"></param>
        /// <param name="outPut"></param>
        public TestBase(ITestOutputHelper outPut)
        {
            var app = new WebApplicationFactory<Startup>().WithWebHostBuilder(builder =>
            {
                //设定环境变量
                builder.UseContentRoot("..\\..\\..\\..\\..\\VisionCloud.Web\\bin\\Debug\\netcoreapp3.1");
                builder.UseWebRoot("..\\..\\..\\..\\VisionCloud.Web\\wwwroot");
                builder.UseEnvironment("Local");
            });
            this.outPut = outPut;
            this.httpClient = app.CreateClient();
            serviceProvider = app.Server.Services;

            var tokenResult = Login().Result;
            if (tokenResult != null)
                httpClient.DefaultRequestHeaders.Add("Authorization", tokenResult.Result?.ToString());
        }

        public T GetService<T>() => serviceProvider.GetService<T>();

        public T GetRequiredService<T>() => serviceProvider.GetRequiredService<T>();

        /// <summary>
        /// post请求
        /// </summary>
        /// <param name="action">单元测试接口的路由</param>
        /// <param name="body">请求内容</param>
        /// <returns></returns>
        public async Task<ApiResult> PostData(string action, dynamic body)
        {
            var content = new StringContent(JsonConvert.SerializeObject(body));
            content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
            var data = await httpClient.PostAsync(action, content);
            var result = await data.Content.ReadAsStringAsync();
            outPut.WriteLine(result);
            var apiReturn = JsonConvert.DeserializeObject<ApiResult>(result);

            return apiReturn;
        }

        /// <summary>
        /// get请求
        /// </summary>
        /// <param name="action">单元测试接口的路由</param>
        /// <returns></returns>
        public async Task<ApiResult> GetData(string action)
        {
            var data = await httpClient.GetAsync(action);
            var result = await data.Content.ReadAsStringAsync();
            outPut.WriteLine(result);
            var apiReturn = JsonConvert.DeserializeObject<ApiResult>(result);

            return apiReturn;
        }

        /// <summary>
        /// 用户授权登录
        /// </summary>
        /// <param name="username">用户名</param>
        /// <param name="password">密码</param>
        /// <returns></returns>
        public async Task<ApiResult> Login(string username = "", string password = "")
        {
            if (string.IsNullOrWhiteSpace(username))
            {
                username = this._userName;
            }

            if (string.IsNullOrWhiteSpace(password))
            {
                password = this._password;
            }
            RSACryptoService rsa = new RSACryptoService(RSACryptoService.DefaultPrivateKey, RSACryptoService.DefaultPublicKey);
            username = rsa.Encrypt(username);
            password = rsa.Encrypt(password);
            var result = await PostData("api/sys/Auth/AuthLogin", new VisionCloud.Domain.DtoModel.Sys.SysUserDto()
            {
                Email = username,
                Password = password,
            });
            // 不要删除初始化用户信息
            await OperatorProvider.Set(result.Result.ToString());
            return result;
        }
    }
}